#include "processor.h"


typedef struct{
unsigned int logicalRegister;
unsigned int localRegister;
}localRMTType;

int processor::preRenamer(unsigned int *indices, unsigned int traceWidth)
{
	
	localRMTType *localRMTInt, *localRMTFloat;

	localRMTInt = new localRMTType[traceWidth];
	localRMTFloat = new localRMTType[traceWidth];
	
	int numLocalRMTEntriesInt = 0, numLocalRMTEntriesFloat = 0;
	
	// First look at destination registers and see if they are local or global or both
	for ( int i = 0; i < traceWidth; i++)
	{
		unsigned int iIndex = indices[i];

		if (PAY.buf[iIndex].C_valid)
		{ // See if the future intructions have the same destination register. If yes, someone is killing it => Not Golbal
			for (int j = i+1; j < traceWidth; j++)
				{
					unsigned int jIndex = indices[j];
					if (PAY.buf[jIndex].C_valid && (PAY.buf[jIndex].C_int == PAY.buf[iIndex].C_int) && (PAY.buf[jIndex].C_log_reg == PAY.buf[iIndex].C_log_reg))
					{
						PAY.buf[iIndex].C_hierarchy &= ~GLOBAL_REGISTER;
						j = traceWidth;
					}

					else //Global
						PAY.buf[iIndex].C_hierarchy |= GLOBAL_REGISTER;

				}


		// Now, to avoid allocating local registers to the Global live-outs only
			unsigned int k, kIndex;
			for (k = i+1; k < traceWidth; k++)
			{
				kIndex = indices[k];

				if (PAY.buf[kIndex].A_valid && (PAY.buf[kIndex].A_log_reg == PAY.buf[iIndex].C_log_reg) && (PAY.buf[kIndex].A_int == PAY.buf[iIndex].C_int))
				{
					PAY.buf[iIndex].C_hierarchy |= LOCAL_REGISTER;
					k = traceWidth;
				}

				if (PAY.buf[kIndex].B_valid && (PAY.buf[kIndex].B_log_reg == PAY.buf[iIndex].C_log_reg) && (PAY.buf[kIndex].B_int == PAY.buf[iIndex].C_int))
				{
					PAY.buf[iIndex].C_hierarchy |= LOCAL_REGISTER;
					k = traceWidth;
				}

			else
				PAY.buf[iIndex].C_hierarchy &= ~LOCAL_REGISTER;
			}

		} //End dst valid
	}//End for loop



	for ( int i = 0; i < traceWidth; i++)
	{
		unsigned int iIndex = indices[i];

		//Rename the sources first. Assume source is a Global Live in
		PAY.buf[iIndex].A_hierarchy = GLOBAL_REGISTER;
		PAY.buf[iIndex].B_hierarchy = GLOBAL_REGISTER;

		//Maintain a local RMT and search through it for each source
		int j = numLocalRMTEntriesInt -1;
		int k = numLocalRMTEntriesFloat -1;

		//Local RMT contains all the mappings that are renamed to locals. One entry per one local register
		if (PAY.buf[iIndex].A_valid)
		{
			for (; j>=0 ; j--)
			{
				if(localRMTInt[j].logicalRegister == PAY.buf[iIndex].A_log_reg && PAY.buf[iIndex].A_int)
				{
					PAY.buf[iIndex].A_loc_reg = localRMTInt[j].localRegister;
					PAY.buf[iIndex].A_hierarchy = LOCAL_REGISTER | ~GLOBAL_REGISTER;
					j = 0;
				}

				if(localRMTFloat[j].logicalRegister == PAY.buf[iIndex].A_log_reg && !PAY.buf[iIndex].A_int)
				{
					PAY.buf[iIndex].A_loc_reg = localRMTFloat[j].localRegister;
					PAY.buf[iIndex].A_hierarchy = LOCAL_REGISTER | ~GLOBAL_REGISTER;
					j = 0;
				}

			}
		}

		if (PAY.buf[iIndex].B_valid)
		{
			for (; k>=0; k--)
			{
				if(localRMTInt[k].logicalRegister == PAY.buf[iIndex].B_log_reg && PAY.buf[iIndex].B_int)
				{
					PAY.buf[iIndex].B_loc_reg = localRMTInt[j].localRegister;
					PAY.buf[iIndex].B_hierarchy = LOCAL_REGISTER | ~GLOBAL_REGISTER;
					k = 0;
				}

				if(localRMTFloat[k].logicalRegister == PAY.buf[iIndex].B_log_reg && !PAY.buf[iIndex].B_int)
				{
					PAY.buf[iIndex].B_loc_reg = localRMTFloat[k].localRegister;
					PAY.buf[iIndex].B_hierarchy = LOCAL_REGISTER | ~GLOBAL_REGISTER;
					k = 0;
				}

			}
		}



		//Destination now:
		//Look at each destinations status register and decide

		if (PAY.buf[iIndex].C_valid && PAY.buf[iIndex].C_int)
		{
			if (PAY.buf[iIndex].C_hierarchy & LOCAL_REGISTER)
			{
				PAY.buf[iIndex].C_loc_reg = numLocalRMTEntriesInt;
				localRMTInt[numLocalRMTEntriesInt].localRegister = numLocalRMTEntriesInt;
				localRMTInt[numLocalRMTEntriesInt].logicalRegister = PAY.buf[iIndex].C_log_reg;
				numLocalRMTEntriesInt ++;
			}
		}

		if (PAY.buf[iIndex].C_valid && !PAY.buf[iIndex].C_int)
		{
			if (PAY.buf[iIndex].C_hierarchy & LOCAL_REGISTER)
			{
				PAY.buf[iIndex].C_loc_reg = numLocalRMTEntriesFloat;
				localRMTInt[numLocalRMTEntriesFloat].localRegister = numLocalRMTEntriesFloat;
				localRMTInt[numLocalRMTEntriesFloat].logicalRegister = PAY.buf[iIndex].C_log_reg;
				numLocalRMTEntriesFloat ++;
			}
		}


	}
	


	return numLocalRMTEntriesInt + numLocalRMTEntriesFloat;
}

